#pragma once
#include "RenderContext.h"

/**
 *	This class is responsible for the rendering.
 */
class Render
{
public:

	static const int FONT_WIDTH = 7;
	static const int FONT_HEIGHT= 14;

	enum RenderEnum {
		TYPE_NONE,
		// primitive type
		TYPE_DOUBLE,
		TYPE_FLOAT,
		TYPE_UNSINGED_INT,
		TYPE_UNSINGED_BYTE,

		// for buffers
		TYPE_INDEX,
		TYPE_VERTEX,
		TYPE_TEXTURE,
		TYPE_COLOR,
		TYPE_NORMAL,
		TYPE_VERTEX_SHADER,
		TYPE_PIXEL_SHADER,
		TYPE_GEOMETRY_SHADER,
		TYPE_COMPUTE_SHADER,
		TYPE_LAYOUT,
		TYPE_BUFFER,

		// render
		RENDER_TYPE_POINT,
		RENDER_TYPE_TRILIST,
		TYPE_SHADER_RESOURCE,
		TYPE_UNORDERED_ACCESS_VIEW,

		// for matrix mode
		MODEL_MATRIX,
		VIEW_MATRIX,
		PROJ_MATRIX,
		MODELVIEW_MATRIX,
		LIGHT0_VIEW_MATRIX,
		LIGHT0_PROJ_MATRIX,
		TEXTURE_MATRIX,

		// enable parameters
		TEXTURE_2D,

		// color
		TYPE_RGB,
		TYPE_RGBA,
		TYPE_R32,

		// texture
		TEXTURE0,
		TEXTURE1,
		TEXTURE2,
		TEXTURE3,

		// enables
		CULL_FACE,
		WIRE_FRAME,
		ALPHA,

		// faces
		FRONT,
		BACK,

	};

	Render(void) {};
	virtual ~Render(void) {};

	/**
	 *	initialize the context
	 */
	virtual void initialize() = 0;

	/**
	 *	clear the context
	 */
	virtual void deinitialize() = 0;

	/**
	 *	clear screen
	 */
	virtual void clear() = 0;

	/**
	 *	swap background buffers
	 */
	virtual void flush() const = 0;

	virtual pint loadShader(const std::string& fileName, int type, const std::string& func, pint* inputLayout = NULL, const VertexDesc* desc = NULL) const = 0;
	virtual pint loadTexture(const std::string& fileName) const = 0;
	virtual void loadMatrix(RenderEnum type, const mat4f& matrix) = 0;

	virtual void applyShader(pint shader, int type) const = 0;

//	virtual void applyShaderResource(int slot, pint res, RenderEnum type = TYPE_COMPUTE_SHADER) = 0;
//	virtual void applyComputeShader(pint shader, int slot, int nViews, void** views, pint uaview, size_t x, size_t y, size_t z) = 0;
//	virtual void createRenderTarget(pint& target, pint& res, pint& depth, int width = 0, int height = 0, RenderEnum format = TYPE_RGBA, bool createDepth = false) {}
//	virtual void setRenderTarget(pint target, pint depth) {}

	virtual void updateResource(pint res, const void* data) const = 0;
	
	virtual pint createVertexBuffer(const void* data, size_t bufferSize) const = 0;
	virtual pint createIndexBuffer(const void* data, size_t size) = 0;
	virtual pint createConstantBuffer(size_t size,const void* data) = 0;

	virtual void setVertexBuffer(const pint buffer, size_t sizeOfVertex, size_t offset) const = 0;
	virtual void setVertexLayout(const pint layout) const = 0;
	virtual void setIndexBuffer(pint buffer, size_t offset = 0) const = 0;
	virtual void setConstantBuffer(pint buffer, RenderEnum type = TYPE_NONE) = 0;

	virtual void deleteBuffer(RenderEnum type,pint bufferId) const = 0;
	virtual void deleteShader(int type,pint bufferId) const = 0;

	virtual void drawIndexBuffer(size_t numIndicies, size_t startIndex = 0, size_t startVertex = 0) const = 0;
//	virtual pint createStructuredBuffer(size_t stride, size_t nCount, pint& srv, pint& uav, const void* data = NULL) = 0;
//	virtual pint createConstantBuffer(size_t size,const void* data = NULL) = 0;
//	virtual void copyResource(pint bufferFrom, pint bufferTo) = 0;
//	virtual pint createAndCopyToDebugBuf( pint buffer ) = 0;
//	virtual void map(pint buffer, void** data) = 0;
//	virtual void unmap(pint buffer) = 0;
//	
//	virtual void loadMatrix(RenderEnum type, void* data = NULL, int id = -1) = 0;
//	virtual void unloadMatrix(RenderEnum type) = 0;

//	virtual void drawBuffer(size_t numIndicies, size_t startVertex=0, RenderEnum renderType=RENDER_TYPE_TRILIST) = 0;
//
//	/**
//	 *	param[in](angle) in degree.
//	 */
//	virtual void setPerspective( float angle, float ratio, float nearz, float farz ) = 0;
//
//	/**
//	 *	@param[in](texFormat) format of texil. Must be TYPE_RGB(24bit), TYPE_RGBA(32bit). Default is TYPE_RGBA
//	 */
//	virtual pint createTexture2D(int width, int height, void* data, RenderEnum srcFmt = TYPE_RGBA) = 0;
//	virtual pint loadTexture(const std::string& fileName) = 0;
//	virtual void applyTexture(int textureIdx, pint texture) = 0;
//	virtual void clearTexture() {}
//
//	virtual void setEnvParameter(float x, float y, float z, float w, size_t id, RenderEnum what = TYPE_VERTEX_SHADER) = 0;
//	virtual void cullFace(RenderEnum face) = 0;
//
//	// helpers
//	virtual void enable(RenderEnum what) = 0;
//	virtual void disable(RenderEnum what) = 0;
//
//	virtual void beginText() = 0;
//	virtual void drawText(const std::string& str, int x, int y, double scaleX=1,double scaleY=1) = 0;
//	virtual void endText() = 0;
//
protected:
	float mClearColor[4];

	unsigned int mMultiSample;
	unsigned int mSampleQuality;
	bool mbWindowed;

	int mWinWidth;
	int mWinHeight;
};